package at.ac.tuwien.isis.infret.ue3;

import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.TreeMap;
import java.util.Vector;

import at.ac.tuwien.isis.infret.helper.DocumentContainer;

public  class Statistics {
	
	public static Double[] getIndexStatistics(Double[][] distanceMatrix, int index){
		//min, max avg
		Double[] stat ={Double.MAX_VALUE, 0.0,0.0};
		for(int i = 0; i < distanceMatrix.length;i++){
			if (i == index) continue;
			
			if(distanceMatrix[index][i]< stat[0])
				stat[0] = distanceMatrix[index][i];
			if(distanceMatrix[index][i]> stat[1])
				stat[1] = distanceMatrix[index][i];
			stat[2] += distanceMatrix[index][i];
			
		}
		stat[2] = stat[2]/((double)distanceMatrix.length);
		return stat;
	}
	public static int getNumberOccur(Double[][] rankMatrix, int index, int kBest){
		int occur =0;
		for (int i = 0; i < rankMatrix.length;i++){
			if (i == index)continue;
			if(rankMatrix[i][index] <= kBest){
				occur++;
			}
		}
		return occur;
	}
	
	

	
	public static HashMap<DocumentContainer,Double> getkBest(Vector<TreeMap<DocumentContainer,Double>>  resultLists,int numberOfDocuments){
		HashMap<DocumentContainer,Double> finished = new HashMap<DocumentContainer,Double>();
		List<Double> bestDistances = new LinkedList<Double>();
		
		for(int i = 0; i < numberOfDocuments; i ++){
			bestDistances.add( Double.MAX_VALUE);
			//System.out.println(bestDistances.size());
		}
		Collections.sort(bestDistances);
		TreeMap<DocumentContainer,Double> map = resultLists.firstElement();
		for(DocumentContainer doc : map.keySet()){
			Double minDistance = Statistics.getMinDistance(doc, resultLists);
			//System.out.println(minDistance +":"+ bestDistances.last());
			
			if(minDistance < bestDistances.get(bestDistances.size()-1)){
				//System.out.println(minDistance +":"+ bestDistances.get(bestDistances.size()-1));
				Double removed = bestDistances.remove(bestDistances.size()-1);
				bestDistances.add(minDistance);
				Collections.sort(bestDistances);
				
				DocumentContainer remDoc=null;
				for(DocumentContainer bestDoc : finished.keySet() ){
					if (finished.get(bestDoc).equals(removed)){
				
						remDoc = bestDoc;
					}
				}
				finished.remove(remDoc);
				finished.put(doc, minDistance);
			}
		}
		//System.out.println(finished.size());
		return finished;
	}
	public static HashMap<DocumentContainer,Double>  getkBestByRank(Vector<TreeMap<DocumentContainer,Double>>  resultLists,int numberOfDocuments){
		HashMap<DocumentContainer,Double> finished = new HashMap<DocumentContainer,Double>();
		List<Double> bestRank = new LinkedList<Double>();
		
		for(int i = 0; i < numberOfDocuments; i ++){
			bestRank.add( Double.MAX_VALUE);
			//System.out.println(bestDistances.size());
		}
		Collections.sort(bestRank);
		TreeMap<DocumentContainer,Double> map = resultLists.firstElement();
		for(DocumentContainer doc : map.keySet()){
			Double newRank = Statistics.avgRank(doc, resultLists);
			//System.out.println(minDistance +":"+ bestDistances.last());
			
			if(newRank < bestRank.get(bestRank.size()-1)){
				//System.out.println(minDistance +":"+ bestDistances.get(bestDistances.size()-1));
				Double removed = bestRank.remove(bestRank.size()-1);
				bestRank.add(newRank);
				Collections.sort(bestRank);
				
				DocumentContainer remDoc=null;
				for(DocumentContainer bestDoc : finished.keySet() ){
					if (finished.get(bestDoc).equals(removed)){
				
						remDoc = bestDoc;
					}
				}
				finished.remove(remDoc);
				finished.put(doc, newRank);
			}
		}
		//System.out.println(finished.size());
		return finished;
	}
	
	public static Double getMinDistance(DocumentContainer doc, Vector<TreeMap<DocumentContainer,Double>>  resultLists){
		Double min = Double.MAX_VALUE;
		for (TreeMap <DocumentContainer, Double> map : resultLists){
			Double mapDistance = map.get(doc);
			if(min > mapDistance)
				min = mapDistance;
		}
		return min;
	}
	
	public static int SumofOcc(DocumentContainer doc, Vector<TreeMap<DocumentContainer,Double>>  resultLists, 
			int kBest){
		
		int occur = 0;
		for(TreeMap< DocumentContainer,Double> map : resultLists){
		
			List<Double> topKBest = new LinkedList<Double>();
			topKBest.addAll(map.values());
			Collections.sort(topKBest);
			int i = 0; 
			for(Double distance : topKBest){
				
				i++;
				
				if(distance.equals(map.get(doc))){
					//System.out.println(distance+"at rank "+i);
					occur++;
					break;
				}
				if(i==kBest) break;
			}
			
			//if(map.containsKey(doc))occur++;
		}
		return occur;
	}
	public static double avgRank(DocumentContainer doc, Vector<TreeMap<DocumentContainer,Double>> resultLists){
		int rank =0;
		//int occur =0; 
		for(TreeMap<DocumentContainer,Double> map : resultLists){
			List<Double> ranking = new LinkedList<Double>();
			ranking.addAll(map.values());
			Collections.sort(ranking);
			//System.out.println(ranking);
			for(Double distance : ranking){
				
				if(distance.equals(map.get(doc))){
					//occur++;
					rank +=ranking.indexOf(distance);
					break;
				}
			}
		}
		//System.out.println(rank+"/"+occur);
		return ((double)rank)/resultLists.size();
	}
	public static Double avgDistance(DocumentContainer doc, Vector<TreeMap<DocumentContainer,Double> > resultLists){
		Double distance =0.0;
		for(TreeMap<DocumentContainer,Double> map : resultLists){
			if(map.get(doc)!=null){
				if(Double.isNaN(map.get(doc)))System.out.println("wtf!");
				distance += map.get(doc);
				
			}
				
		}
		//System.out.println(distance+":"+occur);
		return distance/((double)resultLists.size());
	}
	public static Double[] getkBestStatistics(HashMap<DocumentContainer,Double> kBest)
	{
		//ret holding min, max. average
		Double[] ret = {Double.MAX_VALUE, 0.0, 0.0};
		
		for(DocumentContainer doc : kBest.keySet()){
			Double value = kBest.get(doc);
			ret[2] += value;
			if (value < ret[0])
				ret[0] = value;
			
			if(value > ret[1])
				ret[1] = value;
		}
		ret[2] = ret[2]/((double)kBest.keySet().size());
		
		return ret;
	}
}
